#region " LICENSE "
// DRILL - Dependency Resolution Interface Layer Library
// Copyright (c) 2008-2012 Wade A. Reynolds. All rights reserved.
// http://drill.codeplex.com/
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using Drill.Configuration;
using Drill.Extensibility;

namespace Drill.Core.Builders
{
	public class DependencyResolverBuilder : IDependencyResolverBuilder
	{
		private readonly string _dependencyResolverName;
		private readonly string _dependencyResolverAssemblyQualifiedTypeName;
		private readonly IConfigurationHelperFactory _configurationHelperFactory;
		private readonly IDrillBitSetFactory _drillBitSetFactory;
		private readonly IRootPathProviderFactory _rootPathProviderFactory;
		private readonly ISearchPathFactory _searchPathFactory;

		private IConfigurationHelper _configurationHelper;
		private IDependencyResolver _dependencyResolver;
		private IList<IDrillBit> _drillBits;
		private IDependencyResolverInitContext _initContext;
		private IList<IRootPathProvider> _rootPathProviders;
		private IList<ISearchPath> _searchPaths;

		public DependencyResolverBuilder(
			string dependencyResolverName,
			IConfigurationHelperFactory configurationHelperFactory,
			IDrillBitSetFactory drillBitSetFactory,
			IRootPathProviderFactory rootPathProviderFactory = null,
			ISearchPathFactory searchPathFactory = null,
			string dependencyResolverAssemblyQualifiedTypeName = null
			)
		{
			if (string.IsNullOrEmpty(dependencyResolverName))
			{
				throw new ArgumentNullException("dependencyResolverName");
			}
			if (null == configurationHelperFactory)
			{
				throw new ArgumentNullException("configurationHelperFactory");
			}
			if (null == drillBitSetFactory)
			{
				throw new ArgumentNullException("drillBitSetFactory");
			}
			_dependencyResolverName = dependencyResolverName;
			_configurationHelperFactory = configurationHelperFactory;
			_drillBitSetFactory = drillBitSetFactory;
			_rootPathProviderFactory = rootPathProviderFactory;
			_searchPathFactory = searchPathFactory;
			_dependencyResolverAssemblyQualifiedTypeName = dependencyResolverAssemblyQualifiedTypeName;
		}

		public void BuildConfigurationHelper()
		{
			_configurationHelper = _configurationHelperFactory.CreateConfigurationHelper(_rootPathProviders, _searchPaths);
		}

		public void BuildDrillBits()
		{
			_drillBits = _drillBitSetFactory.CreateDrillBits(_configurationHelper);
		}

		public void BuildInitializationContext()
		{
			_initContext = new DependencyResolverInitContext {DrillBits = _drillBits, Name = _dependencyResolverName};
		}

		public void BuildRootPathProviders()
		{
			_rootPathProviders = (null != _rootPathProviderFactory) ? _rootPathProviderFactory.CreateRootPathProviders() : null;
			if (null == _rootPathProviders || _rootPathProviders.Count < 1)
			{
				// Use the default root path provider.
				_rootPathProviders = new List<IRootPathProvider>{new ExecutingDirectoryRootPathProvider()};
			}
		}

		public void BuildSearchPaths()
		{
			_searchPaths = (null != _searchPathFactory) ? _searchPathFactory.CreateSearchPaths() : null;
		}

		public void CreateDependencyResolver()
		{
			if (string.IsNullOrWhiteSpace(_dependencyResolverAssemblyQualifiedTypeName))
			{
				// When no type is specified, use the built-in default dependency resolver type.
				_dependencyResolver = BuiltInDefaultDependencyResolverFactory.CreateInstance(_initContext);
			}
			else
			{
				var activator =
					new ObjectOrFactoryActivator<
							  IDependencyResolver
							, IDependencyResolverFactory
							, IDependencyResolverInitContext>();

				var activatorResult = activator.CreateInstance(_dependencyResolverAssemblyQualifiedTypeName, _initContext);

				// activatorResult.Item1 = IDependencyResolver
				// activatorResult.Item2 = IDependencyResolverFactory
				_dependencyResolver =
					(null != activatorResult.Item2)
						? activatorResult.Item2.CreateDependencyResolver()
						: activatorResult.Item1;
			}
		}

		public IDependencyResolver GetDependencyResolver()
		{
			return _dependencyResolver;
		}
	}
}